package org.andolphin.client.provider;

import java.util.Date;
import java.util.HashMap;

import org.andolphin.client.utils.DateUtils;
import org.andolphin.client.utils.StringUtils;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

public class PaymentProvider extends ContentProvider {
    public static final String TAG = PaymentProvider.class.getName();

    public static final String DB_TABLE = "payment";
    public static final String DB_NAME = "andolphin";
    public static final int DB_VERSION = 1;
    private static UriMatcher URI_MATCHER = null;
    private static HashMap<String, String> PROJECTION_MAP;
    private static final int PAYMENTS = 1;
    private static final int PAYMENT = 2;
    private static final int PAYMENTS_BY_DATE = 3;
    private static final int PAYMENTS_CATEGORY = 4;
    static {
        PaymentProvider.URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
        PaymentProvider.URI_MATCHER.addURI(PaymentColumns.AUTHORITY, PaymentColumns.PATH_MULTIPLE, PAYMENTS);
        PaymentProvider.URI_MATCHER.addURI(PaymentColumns.AUTHORITY, PaymentColumns.PATH_SINGLE, PAYMENT);
        PaymentProvider.URI_MATCHER.addURI(PaymentColumns.AUTHORITY, PaymentColumns.PATH_MULTIPLE_BY_DATE,
                PAYMENTS_BY_DATE);
        PaymentProvider.URI_MATCHER.addURI(PaymentColumns.AUTHORITY, PaymentColumns.PATH_CATEGORIES, PAYMENTS_CATEGORY);
        PaymentProvider.PROJECTION_MAP = new HashMap<String, String>();
        PaymentProvider.PROJECTION_MAP.put(PaymentColumns._ID, "_id");
        PaymentProvider.PROJECTION_MAP.put(PaymentColumns.COL_KEY, PaymentColumns.COL_KEY);
        PaymentProvider.PROJECTION_MAP.put(PaymentColumns.COL_AMOUNT, PaymentColumns.COL_AMOUNT);
        PaymentProvider.PROJECTION_MAP.put(PaymentColumns.COL_BALANCE, PaymentColumns.COL_BALANCE);
        PaymentProvider.PROJECTION_MAP.put(PaymentColumns.COL_CATEGORY, PaymentColumns.COL_CATEGORY);
        PaymentProvider.PROJECTION_MAP.put(PaymentColumns.COL_EVENT_DATE, PaymentColumns.COL_EVENT_DATE);
        PaymentProvider.PROJECTION_MAP.put(PaymentColumns.COL_DESCRIPTION, PaymentColumns.COL_DESCRIPTION);
        PaymentProvider.PROJECTION_MAP.put(PaymentColumns.COL_LAST_UPDATED, PaymentColumns.COL_LAST_UPDATED);
    }

    private static class DBOpenHelper extends SQLiteOpenHelper {
        private static final String DB_CREATE;
        static {
            StringBuilder sb = new StringBuilder();
            sb.append("CREATE TABLE payment (");
            sb.append("       _id           INTEGER PRIMARY KEY, ");
            sb.append("       key           TEXT, ");
            sb.append("       amount        NUMERIC(10,2) DEFAULT 0,");
            sb.append("       balance       TEXT, ");
            sb.append("       category      TEXT, ");
            sb.append("       description   TEXT, ");
            sb.append("       event_date    CHAR(8), ");
            sb.append("       last_updated  CHAR(14)");
            sb.append(");");
            DB_CREATE = sb.toString();
        }

        public DBOpenHelper(Context context) {
            super(context, PaymentProvider.DB_NAME, null, PaymentProvider.DB_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            try {
                db.execSQL(DBOpenHelper.DB_CREATE);
            } catch (SQLException e) {
                Log.i(TAG, StringUtils.digMessage(e), e);
            }
        }

        @Override
        public void onOpen(SQLiteDatabase db) {
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL("DROP TABLE IF EXISTS " + PaymentProvider.DB_TABLE);
            this.onCreate(db);
        }
    }

    private SQLiteDatabase db;

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        int count = 0;
        switch (PaymentProvider.URI_MATCHER.match(uri)) {
        case PAYMENTS:
            count = this.db.delete(PaymentProvider.DB_TABLE, selection, selectionArgs);
            break;
        case PAYMENT:
            String segment = uri.getPathSegments().get(1);
            String where = TextUtils.isEmpty(selection) ? "" : " AND (" + selection + ")";
            count = this.db.delete(PaymentProvider.DB_TABLE, "_id=" + segment + where, selectionArgs);
            break;
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
        }
        return count;
    }

    @Override
    public String getType(Uri uri) {
        switch (PaymentProvider.URI_MATCHER.match(uri)) {
        case PAYMENTS:
            return PaymentColumns.MIME_TYPE_MULTIPLE;
        case PAYMENT:
            return PaymentColumns.MIME_TYPE_SINGLE;
        case PAYMENTS_BY_DATE:
            return PaymentColumns.MIME_TYPE_MULTIPLE;
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
        }
    }

    @Override
    public Uri insert(Uri uri, ContentValues initialValues) {
        long rowId = 0L;
        ContentValues values = null;
        if (initialValues != null) {
            values = new ContentValues(initialValues);
        } else {
            values = new ContentValues();
        }
        if (PaymentProvider.URI_MATCHER.match(uri) != PaymentProvider.PAYMENTS) {
            throw new IllegalArgumentException("Unknown URI " + uri);
        }
        // 当前时间
        Date now = DateUtils.now();
        if (!values.containsKey(PaymentColumns.COL_LAST_UPDATED)) {
            values.put(PaymentColumns.COL_LAST_UPDATED, DateUtils.formatDate(now));
        }
        values.put(PaymentColumns.COL_LAST_UPDATED, DateUtils.formatDateTime(now));
        rowId = this.db.insert(PaymentProvider.DB_TABLE, "", values);
        if (rowId > 0) {
            Uri result = ContentUris.withAppendedId(PaymentColumns.CONTENT_URI, rowId);
            this.getContext().getContentResolver().notifyChange(result, null);
            return result;
        } else {
            throw new SQLException("Failed to insert row into " + uri);
        }
    }

    @Override
    public boolean onCreate() {
        DBOpenHelper dbHelper = new DBOpenHelper(this.getContext());
        this.db = dbHelper.getWritableDatabase();
        if (this.db == null) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
        String orderBy = null;
        switch (URI_MATCHER.match(uri)) {
        case PAYMENTS:
            queryBuilder.setTables(DB_TABLE);
            queryBuilder.setProjectionMap(PROJECTION_MAP);
            break;
        case PAYMENT:
            queryBuilder.setTables(DB_TABLE);
            queryBuilder.appendWhere("_id=" + uri.getPathSegments().get(1));
            break;
        case PAYMENTS_BY_DATE:
            queryBuilder.setTables(DB_TABLE);
            queryBuilder.setProjectionMap(PROJECTION_MAP);
            String p = uri.getPathSegments().get(2);
            if (DateUtils.parseDate(p) == null) {
                throw new IllegalArgumentException("Unknown DATE: " + p);
            }
            queryBuilder.appendWhere("event_date=" + p);
            break;
        case PAYMENTS_CATEGORY:
            queryBuilder.setTables(DB_TABLE);
            queryBuilder.setDistinct(true);
            projection = new String[] { PaymentColumns.COL_CATEGORY };
            sortOrder = PaymentColumns.COL_CATEGORY + " desc";
            break;
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
        }
        if (TextUtils.isEmpty(sortOrder)) {
            orderBy = PaymentColumns.DEFAULT_SORT_ORDER;
        } else {
            orderBy = sortOrder;
        }
        Cursor c = queryBuilder.query(this.db, projection, selection, selectionArgs, null, null, orderBy);
        c.setNotificationUri(this.getContext().getContentResolver(), uri);
        return c;
    }

    @Override
    public int update(Uri uri, ContentValues initialValues, String selection, String[] selectionArgs) {
        ContentValues values = new ContentValues(initialValues);
        int count = 0;
        values.put(PaymentColumns.COL_LAST_UPDATED, DateUtils.formatDateTime(DateUtils.now()));
        switch (PaymentProvider.URI_MATCHER.match(uri)) {
        case PAYMENTS:
            count = this.db.update(PaymentProvider.DB_TABLE, values, selection, selectionArgs);
            break;
        case PAYMENT:
            String segment = uri.getPathSegments().get(1);
            String where = TextUtils.isEmpty(selection) ? "" : " AND (" + selection + ")";
            count = this.db.update(PaymentProvider.DB_TABLE, values, "_id=" + segment + where, selectionArgs);
            break;
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
        }
        return count;
    }
}
